package com.campus.common.bean.common;

import org.apache.commons.lang3.reflect.FieldUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @project: service
 * @description: 树状结构工具类
 * @author: zhaoyujie
 * @create: 2020-12-23 18:21
 */
public class TreeUtil {

    /**
     * 封装集合成树状结构,默认对象标识为id，父标识为pid，子节点集合是children
     * @param nodes 原始对象集合
     * @return 组装树状结构后的集合
     */
    public static <T> List<T> buildTree(List<T> nodes) {
        return buildTree(nodes,"id","pid","children");
    }

    /**
     * 封装集合成树状结构（不需要从顶级节点计算）
     * @param nodes 原始对象集合
     * @param idFieldName 对象属性ID名称
     * @param pidFieldName 对象属性父ID名称
     * @param childrenFieldName 子集合属性名称
     * @param <T>
     * @return 组装树状结构后的集合
     */
    public static <T> List<T> buildTree(List<T> nodes, String idFieldName, String pidFieldName,String childrenFieldName) {
        Map<String, List<T>> children = nodes.stream()
                .collect(Collectors.groupingBy(node -> getFieldValueByFieldName(node,pidFieldName)));
        nodes.forEach(node -> {
            try {
                FieldUtils.writeField(node, childrenFieldName, children.get(getFieldValueByFieldName(node,idFieldName)), true);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });

        List<String> idFieldNameList = nodes.stream().map(node -> getFieldValueByFieldName(node, idFieldName)).collect(Collectors.toList());

        return nodes.stream().filter(node -> !idFieldNameList.contains(getFieldValueByFieldName(node,pidFieldName))).collect(Collectors.toList());
    }


    public static String getFieldValueByFieldName(Object object,String fieldName) {
        try {
            Field field = object.getClass().getDeclaredField(fieldName);
            //对private的属性的访问
            field.setAccessible(true);
            return String.valueOf(field.get(object));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

}
